package se.sics.kompics.tutorial.tutorial2.unreliableBroadcast;

import java.util.Set;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import se.kth.ict.id2203.flp2p.FairLossPointToPointLink;
import se.kth.ict.id2203.flp2p.Flp2pSend;
import se.sics.kompics.ComponentDefinition;
import se.sics.kompics.Handler;
import se.sics.kompics.Negative;
import se.sics.kompics.Positive;
import se.sics.kompics.address.Address;
import se.sics.kompics.tutorial.tutorial2.lazyProbabilisticBcast.messages.DataMessage;
import se.sics.kompics.tutorial.tutorial2.unreliableBroadcast.events.UnBroadcast;
import se.sics.kompics.tutorial.tutorial2.unreliableBroadcast.events.UnDeliver;

public final class UnreliableBroadcastImpl extends ComponentDefinition {
	
	Positive<FairLossPointToPointLink> flp2p = requires(FairLossPointToPointLink.class);
	Negative<UnreliableBroadcast> unBr = provides(UnreliableBroadcast.class);
	
	private static final Logger logger = LoggerFactory.getLogger(UnreliableBroadcastImpl.class);
	
	private Set<Address> neighborSet;
	//private Address self;
	
	public UnreliableBroadcastImpl(){
		subscribe(handleInit, control);
		subscribe(handleUnBcastRequest, unBr);
		subscribe(handleUnBcastedReception, flp2p);
	}
	
	// Handle the reception of a unBroadcasted message
	Handler<DataMessage> handleUnBcastedReception = new Handler<DataMessage>() {
		@Override
		public void handle(DataMessage event) {
			trigger(new UnDeliver(event.getSource(), event), unBr);
		}
	};
	
	// UnBroadcast a message
	Handler<UnBroadcast> handleUnBcastRequest = new Handler<UnBroadcast>(){
		@Override
		public void handle(UnBroadcast event) {
			if (event.getMessage().getClass() == DataMessage.class) {
				logger.info("Message sent.");
				for(Address node : neighborSet){
					trigger(new Flp2pSend(node, event.getMessage()), flp2p);
				}
			}
		}
		
	};
	
	// Init Handler
	Handler<UnreliableBroadcastInit> handleInit = new Handler<UnreliableBroadcastInit>() {
		public void handle(UnreliableBroadcastInit event) {
			// Topology init
			neighborSet = event.getNeighborSet();
			//self = event.getSelf();
		}
	};
	
	/* Start handler
	Handler<Start> handleStart = new Handler<Start>() {
		public void handle(Start event) {
			
		}
	};*/
}